package data_operater

import (
	"context"
	"fmt"
)

type SetterType string

const (
	SetterTypeProp  SetterType = "prop"
	SetterTypeArray SetterType = "array"
)

func SetData(ctx context.Context, obj interface{}, path string, dataProvider SetterDataProvider) (err error) {
	defer func() {
		if e := recover(); e != nil {
			if v, ok := e.(error); ok {
				err = fmt.Errorf("SetData panic: %w", v)
				return
			}
			err = fmt.Errorf("SetData panic: %v", e)
		}
	}()

	stateMover := NewStateMoveManager(
		Start2FieldMove{},
		Op2OpMove{},
		OpEnd2FieldMove{},
		OpEnd2OpStartMove{},
		OpStart2FieldMove{},
		OpStart2OpEndMove{},
		Field2OpStartMove{},
		Field2FieldMove{},
	)
	tokens, err := parseToken(stateMover, path)
	if err != nil {
		return err
	}
	setters := make([]Setter, 0)
	for _, token := range tokens {
		switch token.tokenType {
		case Field:
			lastSetterIndex := len(setters) - 1
			if lastSetterIndex < 0 {
				setters = append(setters, NewPropSetter(token.value))
			} else {
				// 最后一个节点有子节点时，链接到子节点上
				newSetter := NewPropSetter(token.value)
				if setters[lastSetterIndex].GetChild() != nil {
					if err := setters[lastSetterIndex].SetChildNext(newSetter); err != nil {
						return err
					}
				} else {
					setters[lastSetterIndex].SetNext(newSetter)
				}
				setters = append(setters, newSetter)
			}
		case OpArray:
			lastSetterIndex := len(setters) - 1
			if lastSetterIndex < 0 {
				panic("解释器错误：数组操作符前setter栈为空")
			}
			lastSetter := setters[lastSetterIndex]
			// 设置子组件为arraySetter
			newSetter, err := NewArraySetter(token.value)

			err = lastSetter.SetChild(newSetter)
			if err != nil {
				return fmt.Errorf("解析器错误：%s", err.Error())
			}

		case OpProp:
			continue
		case OpMergeField:
			return fmt.Errorf("setter模式中不支持|符号")
		}
	}
	// 直接执行第一个getter
	return setters[0].Set(ctx, obj, obj, dataProvider)
}
